var frate=1000.0/22;
var canvasWidth;
var canvasHeight;
var currentWindow;
var stepSize=1.92;
var currentStep=-1;
var prevStep=-2;
var player;
var canvas;
var context2D;
var flashCounter=0;
var far=0.05;
var dots;
var dotCount=200;
var startDotWidth=5;
var dotSpeedRatio=1.0;
var nn=0;

function resizeCanvas(){
	var w=currentWindow.width()-8;
	var h=currentWindow.height()-8;
	if(canvasWidth!=w){canvasWidth=w;canvas.width=w;}
	if(canvasHeight!=h){canvasHeight=h;canvas.height=h;}
	}
function drawBar(){
	var barWidth=(canvasWidth-16-16)/14;
	context2D.fillStyle="rgba(255, 255, 255, 0.05)";
	for(var i=0;i<14;i++){
		context2D.fillRect(16+barWidth*i, canvasHeight-16-16, barWidth-1, 16);
		}
	var nn=Math.round((currentStep-5)/10);
	context2D.fillRect(16+barWidth*nn, canvasHeight-16-16, barWidth-1, 16);
	}
function step(){
	/*
	0 - very slow
	8 - slow, 15 - transition
	16 - beat, 31 - transition
	32 - voice by 2
	40 - slow
	42 - beat, 49 - transition
	50 - voice
	57 - transition
	58 - voice
	66 - slow
	74 - voice, 81 - transition
	82 - voice
	90 - beat, 105 - transition
	106 - voice
	114 - beat
	122 - slow
	130 - very slow
	131 cut half
	*/
	if(currentStep==32 || currentStep==34 || currentStep==36 || currentStep==38
				|| currentStep==50 || currentStep==52 || currentStep==54 || currentStep==56 || currentStep==58 || currentStep==60 || currentStep==62 || currentStep==64
				|| currentStep==74 || currentStep==76 || currentStep==78 || currentStep==80 || currentStep==82 || currentStep==84 || currentStep==86 || currentStep==88
				|| currentStep==106 || currentStep==108 || currentStep==110 || currentStep==112
				){
		flashCounter=1.0;
		}
	
	}
function resetDot(dot){
	dot.x=(Math.random()*canvasWidth-canvasWidth*0.5)*startDotWidth;
	dot.y=(Math.random()*canvasHeight-canvasHeight*0.5)*startDotWidth;
	dot.a=startDotWidth;
	dot.b=0;
	dot.c=0;
	}	
function drawDots(){
	var dot;
	dotStep=dotSpeedRatio*far/15.0;
	for(i=0;i<dotCount;i++){
		dot=dots[i];
		var x=dot.x/dot.a;
		var y=dot.y/dot.a;
		var z=1/dot.a * 3 + 1;
        if(dot.b != 0) {
            context2D.strokeStyle="rgba(255,255,255,0.2)";
            context2D.lineWidth=z;
            context2D.beginPath();
            context2D.moveTo(x+canvasWidth/2,y+canvasHeight/2);
            context2D.lineTo(dot.b+canvasWidth/2,dot.c+canvasHeight/2);
            context2D.stroke();
        	}
        dot.b=x;
        dot.c=y;
        dot.a=dot.a-dotStep;
        if(dot.a<dotStep || dot.b>canvasWidth || dot.c>canvasHeight){
			resetDot(dot);
			}
		}
	}
function setFar(){
	far=1;
	dotSpeedRatio=1.0;
	if(currentStep>7 && currentStep<16)far=(currentStep-7)*0.055;
	if(currentStep>121 && currentStep<130)far=(130-currentStep)*0.055;
	if(currentStep>=130 || currentStep<=7)far=0.05;
	if(currentStep>=32 && currentStep<40){far=0.5;dotSpeedRatio=5;}
	if(currentStep>=50 && currentStep<66){far=0.5;dotSpeedRatio=3;}
	if(currentStep>=74 && currentStep<90){far=0.5;dotSpeedRatio=3;}
	if(currentStep>=106 && currentStep<114){far=0.5;dotSpeedRatio=3;}
	if(currentStep>=66 && currentStep<74)far=0.3;
	}
function drawStatus(){
	context2D.fillStyle = '#999999';
	context2D.textBaseline="top";
	context2D.fillText("F11 for http://habrahabr.ru/special/microsoft/webmatrix/works/",2,2);
	context2D.fillText("Author: Sergey Surikov, sss1024@gmail.com, 7 nov 2011",2,12);
	context2D.fillText("Music: Electric Funky - You Got (Creative Commons License)",2,22);
	context2D.fillText("Requirements: Internet Explorer 9",2,32);	
	context2D.fillText("Counter: "+currentStep+" / "+player.currentTime,2,42);
	
	}
function drawFlash(){
	if(flashCounter>0){
		context2D.fillStyle="rgba(255, 255, 255, "+flashCounter+")";
		context2D.fillRect(0, 0, canvasWidth, canvasHeight);
		flashCounter=flashCounter-0.07;
		}
	}
function ray(fromX,fromY,toX,toY){
	var ray1=context2D.createLinearGradient(fromX,fromY,toX,toY);
	ray1.addColorStop(0, "rgba(255,255,255,0)");
	ray1.addColorStop(0.5, "rgba(255,255,255,0.2)");
	ray1.addColorStop(1, "rgba(255,255,255,0)");
	context2D.strokeStyle=ray1;
	context2D.lineWidth=2;
	context2D.beginPath();
	context2D.moveTo(fromX,fromY);
	context2D.lineTo(toX,toY);
	context2D.stroke();
	}
function drawStar(color,xRatio,yRatio,speed,sqew){
		var size=100;
		
		var sinTime=Math.sin(player.currentTime*speed);
		var cosTime=Math.cos(player.currentTime*speed);
		
		var zoom=1.2+Math.sin(player.currentTime*speed+sqew);
		var zoomSize=size*zoom;
		var pathWidth=xRatio*canvasWidth;
		var xShift=(canvasWidth-pathWidth)/2;
		var x=xShift+pathWidth*((sinTime+1)/2);		
		var pathHeight=yRatio*canvasHeight;
		var yShift=(canvasHeight-pathHeight)/2;
		var y=yShift+pathHeight*((cosTime+1)/2);
		
		var drawX=far*x+(canvasWidth-far*canvasWidth)/2;
		var drawY=far*y+(canvasHeight-far*canvasHeight)/2;
		var drawSize=far*zoomSize;
		
		var nn=4.0*player.currentTime/stepSize-Math.floor(4.0*player.currentTime/stepSize);
		var abs=1-Math.sin(nn);
		//if(abs<0.5)abs=0;
		var sin=0.3*drawSize*abs;	
		ray(drawX+drawSize/2		,drawY+drawSize/2-4*sin
			,drawX+drawSize/2		,drawY+drawSize/2+4*sin);
		ray(drawX+drawSize/2-4*sin	,drawY+drawSize/2
			,drawX+drawSize/2+4*sin	,drawY+drawSize/2);
		ray(drawX+drawSize/2-3*sin	,drawY+drawSize/2-3*sin
			,drawX+drawSize/2+3*sin	,drawY+drawSize/2+3*sin);
		
		var coloredCircle = context2D.createRadialGradient(drawX+drawSize/1.7,drawY+drawSize/1.7,1,drawX+drawSize/2,drawY+drawSize/2,drawSize/2+1);
		coloredCircle.addColorStop(0.0,color);
		coloredCircle.addColorStop(1.0,"rgba(0,0,0,0)");
		context2D.fillStyle=coloredCircle;		
		context2D.fillRect(drawX-1, drawY-1, drawSize+2, drawSize+2);
		
		var ball = context2D.createRadialGradient(drawX+drawSize/2,drawY+drawSize/2,1,drawX+drawSize/2,drawY+drawSize/2,drawSize/2+1);
		ball.addColorStop(0.1,"rgba(255,255,255,1)");
		ball.addColorStop(0.5,"rgba(255,255,255,0.1)");
		ball.addColorStop(1.0,"rgba(255,255,255,0)");
		context2D.fillStyle=ball;		
		context2D.fillRect(drawX-1, drawY-1, drawSize+2, drawSize+2);
		}
function tick(){
	resizeCanvas();
	context2D.clearRect(0,0,canvasWidth,canvasHeight);
	currentStep=Math.round((player.currentTime-stepSize/2.0)/stepSize);		
	if(prevStep!=currentStep){
		prevStep=currentStep;
		step();
		}
	setFar();
	drawDots();
	drawStar('#0000ff',1.2,0.8,-0.9,-Math.PI/1.5);
	drawStar('#00ff00',0.7,1.1,1.2,-Math.PI/3);
	drawStar('#ff0000',0.8,1.2,1.5,Math.PI/3);
	drawBar();
	drawStatus();
	drawFlash();
	setTimeout("tick()",frate);
	}	
function initAll(){
	currentWindow=$(window);
	player=document.getElementById('player');
	player.addEventListener('ended',function(){
				this.currentTime=0;
				this.pause();
				this.play();
				}
			,false);
	canvas=document.getElementById('canvas');
	context2D=canvas.getContext('2d');	
	$("#canvas").click(function(e){
		if(e.pageX>16 
					&& e.pageX<canvasWidth-16
					&& e.pageY>canvasHeight-16-16
					&& e.pageY<canvasHeight-16){
			var nn=Math.floor((e.pageX-16)/((canvasWidth-16-16)/14));
			player.currentTime=nn*10*stepSize;
			}
		}); 
	resizeCanvas();
	dots=[];
	var a;
	for(i=0;i<dotCount;i++){
		a={};
    	resetDot(a);
    	dots.push(a);
		}
	tick();
	}
